package jmine.tec.test.junit3;

import java.util.Arrays;
import java.util.Date;
import java.util.List;

import jmine.tec.utils.Tuple;
import junit.framework.TestCase;

/**
 * TestCase que implementa a comparacao por double para evitar erros de aproximacao
 * 
 * @author takeshi
 */
public abstract class DoubleTestCase extends TestCase {
    private static final double DEFAULT_PRECISION = 0.000000000001;

    private double precision = DEFAULT_PRECISION;

    /**
     * @return the precision
     */
    public final double getPrecision() {
        return this.precision;
    }

    /**
     * @param precision the precision to set
     */
    public final void setPrecision(final double precision) {
        this.precision = Math.abs(precision);
    }

    /**
     * @param d0 the first double
     * @param d1 the second double
     */
    public void assertEquals(final double d0, final double d1) {
        if (Math.abs(d0 - d1) > this.precision) {
            fail("Expected: " + String.valueOf(d0) + " but was: " + String.valueOf(d1));
        }
    }

    /**
     * @param message {@link String} the message
     * @param d0 the first double
     * @param d1 the second double
     */
    public void assertEquals(final String message, final double d0, final double d1) {
        if (Math.abs(d0 - d1) > this.precision) {
            fail(message);
        }
    }

    /**
     * @param s0 the first series
     * @param s1 the second series
     */
    public void assertEquals(final double[] s0, final double[] s1) {
        String s0Str = this.toString(s0);
        String s1Str = this.toString(s1);
        this.assertEquals("Expected: " + s0Str + " but was: " + s1Str, s0, s1);
    }

    /**
     * @param serie Serie que deve virar string
     * @return String que descreve a serie
     */
    private String toString(final double[] serie) {
        return Arrays.toString(serie);
    }

    /**
     * @param message {@link String} the message
     * @param s0 the first series
     * @param s1 the second series
     */
    public void assertEquals(final String message, final double[] s0, final double[] s1) {
        if (s0 == s1) {
            return;
        }
        if (s0 == null || s1 == null || s0.length != s1.length) {
            fail(message);
        }
        for (int i = 0; i < s0.length; i++) {
            this.assertEquals(message + ". O erro est� na posicao " + i, s0[i], s1[i]);
        }
    }

    /**
     * @param list points of the serie
     * @return array with only the values of serie
     */
    protected double[] getDoubleArray(final List<Tuple<Date, Double>> list) {

        double[] array = new double[list.size()];
        int i = 0;
        for (Tuple<Date, Double> point : list) {
            array[i++] = point.getTail().doubleValue();
        }
        return array;
    }

    /**
     * @param list values of the serie, as Double
     * @return array with only the values of serie.
     */
    protected double[] getDoubleArrayValues(final List<Double> list) {

        double[] array = new double[list.size()];
        int i = 0;
        for (Double point : list) {
            array[i++] = point.doubleValue();
        }
        return array;
    }
}
